/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const { Scr } = require("../XDefine");
const { X2DBeta } = require("./X2DInterface");
const { XTexture } = require("./XTexture");

class XFbo {
    constructor(options) {
        this.bInited_ = false;
        this.w_ = -1;
        this.h_ = -1;
        this.clearColor_ = [1, 1, 1, 1];
        let w = Scr.logicw;
        let h = Scr.logich;
        if (options) {
            if (options.w) {
                w = options.w;
            }
            if (options.h) {
                h = options.h;
            }
            if (options.color) {
                this.clearColor_ = options.color;
            }
        }
        this.reInit(w, h);
    }
    reInit(w, h) {
        if (this.w_ == w && this.h_ == h) {
            return;
        }
        let gl = window.gl;
        if (this.bInited_) {
            gl.deleteFramebuffer(this.frameBuffer_);
            gl.deleteTexture(this.tex_);
            gl.deleteRenderbuffer(this.renderBuffer_);
            delete XTexture.ximages[this.rid_];
            delete XTexture.all_cuts[this.cid_];
        }

        this.w_ = w;
        this.h_ = h;

        this.tex_ = gl.createTexture() //创建纹理对象
        XTexture._init_texture_status(this.tex_);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

        this.renderBuffer_ = gl.createRenderbuffer();
        gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer_);
        gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h);

        this.frameBuffer_ = gl.createFramebuffer();
        gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer_) //绑定帧缓冲区对象
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.tex_, 0);
        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderBuffer_);

        let e = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
        if (gl.FRAMEBUFFER_COMPLETE !== e) { //gl.FRAMEBUFFER_COMPLETE 表示帧缓冲区对象已正确配置
            console.log('帧缓冲区配置不正确: ' + e.toString());
        }

        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
        gl.bindTexture(gl.TEXTURE_2D, null);
        gl.bindRenderbuffer(gl.RENDERBUFFER, null);

        this.rid_ = XTexture.PutTexture(this.tex_, w, h);
        this.cid_ = XTexture.MakeCut(this.rid_, 0, 0, w, h, w, h);
        this.bInited_ = true;
    }
    Begin(clear = true) {
        X2DBeta.Flush();
        X2DBeta.PushMatrix();
        X2DBeta.WORLD_MAT.Unit()
        X2DBeta.WORLD_MAT.X2DMat(0, 0, this.w_, this.h_);
        X2DBeta.TEXT_MAT.Unit()
        X2DBeta.TEXT_MAT.X2DMat(0, 0, this.w_, this.h_);
        X2DBeta.WORLD_MAT.Scale(1, -1, 1);
        X2DBeta.TEXT_MAT.Scale(1, -1, 1);
        window.gl.bindFramebuffer(window.gl.FRAMEBUFFER, this.frameBuffer_);
        window.gl.viewport(0, 0, this.w_, this.h_);
        if (clear) {
            window.gl.clearColor(...this.clearColor_);
            window.gl.clear(window.gl.COLOR_BUFFER_BIT | window.gl.DEPTH_BUFFER_BIT);
        }
    }
    End(gen = true) {
        X2DBeta.Flush();
        if (gen) {
            window.gl.bindTexture(window.gl.TEXTURE_2D, this.tex_);
            window.gl.generateMipmap(window.gl.TEXTURE_2D);
        }
        window.gl.bindFramebuffer(window.gl.FRAMEBUFFER, null);
        X2DBeta.PopMatrix();
        window.gl.viewport(0, 0, Scr.realw, Scr.realh);
    }
    Draw(x, y, sw = 1, sh = 1, ra = 0, ox = -1, oy = -1, c = 0xffffffff) {
        X2DBeta.drawCut(this.cid_, x, y, sw, sh, ra, ox, oy, c);
    }
    getPixel(x, y) {
        //从this.tex_中读取像素点
        let gl = window.gl;
        gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer_);
        let pixel = new Uint8Array(4);
        gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
        return pixel;
    }
}

module.exports = {
    XFbo
}